#pragma once
#include "syntaxtree.h"
typedef struct Operand_ *Operand;
typedef struct InterCode_ *InterCode;
typedef struct twoop_ *twoop;
typedef struct threeop_ *threeop;
typedef struct gotoop_ *gotoop;
typedef struct stack_ *stack;
struct stack_
{
    Operand node;
    struct stack_ *next;
};
struct Operand_
{
    enum
    {
        TEMP_VARIABLE,
        VARIABLE,
        CONSTANT,
        ADDRESS,
        FUNCTION,
        OP_RELOP,
        LABEL,
        CON_FLOAT,
        OFFSET
    } kind;
    union
    {
        char *name;
        int var_no;
        int value;
        float value_f;
    } u;
};

struct twoop_
{
    Operand result, op;
};

struct threeop_
{
    Operand result, op1, op2;
};

struct gotoop_
{
    Operand op1, relop, op2, label;
};

struct InterCode_
{
    enum
    {
        IC_Label,
        IC_Func,
        IC_Assign,
        IC_Add,
        IC_Sub,
        IC_Mul,
        IC_Div,
        IC_Goto,
        IC_If,
        IC_Retrun,
        IC_Dec,
        IC_Arg,
        IC_Call,
        IC_Param,
        IC_Read,
        IC_Write
    } kind;
    union
    {
        twoop tw;
        threeop th;
        Operand pa;
        gotoop go;
    } u;
    struct InterCode_ *next;
    struct InterCode_ *prev;
};

//创建中间代码头节点
InterCode CreateInterCodeHead();
//创建有两个操作数的中间代码
void CreateInterCodeNodeTwoop(int kind, twoop tw, InterCode head);
//创建有三个操作数的中间代码
void CreateInterCodeNodeThreeop(int kind, threeop th, InterCode head);
//创建只有一个操作数的中间代码
void CreateInterCodeNodeOneop(int kind, Operand op, InterCode head);
//创建GOTO语句（四个操作数）
void CreateInterCodeNodeGOTO(int kind, gotoop go, InterCode head);
//创建Var类型变量
Operand CreateOperandVar(int kind, char *name);
//创建临时变量
Operand CreateOperandTemp(int kind);
//创建代表偏移的临时变量
Operand CreateOperandOffset(int kind);
//创建常量
Operand CreateOperandConst(int kind, int value);
//创建三操作数数据结构
threeop CreateThreeop(Operand result, Operand op1, Operand op2);
//创建二操作数数据结构
twoop CreateTwoop(Operand result, Operand op);
//创建新label
Operand newLabel();
//创建新的GOTO语句所需的四操作数结构
gotoop CreateGotoOp(Operand op1, Operand relop, Operand op2, Operand label);
//分析变量，获得名字
char *getName(Operand op);
//输出结果
void outputInterCode();

void trans_Program(NODE *node);
void trans_ExtDeflist(NODE *node);
void trans_ExtDef(NODE *node);
void trans_FunDec(NODE *node);
void trans_VarList(NODE *node);
void trans_ParamDec(NODE *node);
Operand trans_VarDec(NODE *node, int trans_kind);
void trans_Compst(NODE *node);
void trans_DefList(NODE *node);
void trans_Def(NODE *node);
void trans_DecList(NODE *node);
void trans_Dec(NODE *node);
void trans_StmtList(NODE *node);
void trans_Stmt(NODE *node);
Operand trans_Cond(NODE *node, Operand label_true, Operand label_false);
Operand trans_Exp(NODE *node);
Operand trans_ExpOneNode(NODE *node);
Operand trans_ExpTwoNode(NODE *node);
Operand trans_ExpThreeNode(NODE *node);
Operand trans_ExpFourNode(NODE *node);
Operand trans_Args(NODE *node);
//创建队列头结点
void stackHead();
//插入队列
void insert(Operand op);